import serial


class Relay:
    def __init__(self, port: str = "/dev/ttyUSB0", baudrate: int = 115200, timeout: float = 1.0):
        self._ser = serial.Serial(port=port, baudrate=baudrate, timeout=timeout)

    def open(self) -> None:
        if not self._ser.is_open:
            self._ser.open()
        self._ser.write(b"\x00\x00\x00\x01")
        self._ser.flush()

    def close(self) -> None:
        if not self._ser.is_open:
            self._ser.open()
        self._ser.write(b"\x00\x00\x00\x00")
        self._ser.flush()

    def close_port(self) -> None:
        if self._ser.is_open:
            self._ser.close()

    def __enter__(self):
        return self

    def __exit__(self, exc_type, exc_val, exc_tb):
        self.close_port()


def _run_cli():
    import argparse
    import sys
    import time

    parser = argparse.ArgumentParser(description="Relay tester for /dev/ttyUSB0")
    parser.add_argument("--port", default="/dev/ttyUSB0", help="Serial port, e.g. /dev/ttyUSB0")
    parser.add_argument("--baudrate", type=int, default=115200, help="Baud rate, default 115200")
    parser.add_argument("--timeout", type=float, default=1.0, help="Serial timeout seconds")
    parser.add_argument("--action", choices=["open", "close", "toggle", "interactive"], default="interactive", help="Action to perform")
    parser.add_argument("--delay", type=float, default=0.5, help="Delay seconds for toggle action")
    parser.add_argument("--repeat", type=int, default=1, help="Repeat count for toggle action")
    args = parser.parse_args()

    try:
        with Relay(port=args.port, baudrate=args.baudrate, timeout=args.timeout) as r:
            if args.action == "open":
                r.open()
                print("Sent: 00 00 00 01 (relay ON)")
            elif args.action == "close":
                r.close()
                print("Sent: 00 00 00 00 (relay OFF)")
            elif args.action == "toggle":
                for i in range(args.repeat):
                    r.open()
                    print(f"[{i+1}/{args.repeat}] Sent: 00 00 00 01 (relay ON)")
                    time.sleep(args.delay)
                    r.close()
                    print(f"[{i+1}/{args.repeat}] Sent: 00 00 00 00 (relay OFF)")
                    if i < args.repeat - 1:
                        time.sleep(args.delay)
            else:  # interactive
                print("Interactive mode: input 1=open, 0=close, q=quit")
                while True:
                    try:
                        s = input("> ").strip()
                    except EOFError:
                        print("EOF received, exiting.")
                        break
                    except KeyboardInterrupt:
                        print("\nInterrupted, exiting.")
                        break

                    if s == "1":
                        r.open()
                        print("Sent: 00 00 00 01 (relay ON)")
                    elif s == "0":
                        r.close()
                        print("Sent: 00 00 00 00 (relay OFF)")
                    elif s.lower() in ("q", "quit", "exit"):
                        print("Bye.")
                        break
                    else:
                        print("Invalid input. Please enter 1, 0, or q.")
    except serial.SerialException as e:
        print(f"Serial error: {e}")
        print("Hint: check port path, permissions (dialout group), and baudrate.")
        sys.exit(1)


if __name__ == "__main__":
    _run_cli()